﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.Specialized;

namespace Cephei.Core
{
    namespace Base
    {
        public interface IVector { }
        public interface IMatrix { }
        public interface ICube { }
    }
    public interface ICollection : ICell
    {
        ICell this[string key] { get; set; }
    }

    /// <summary>
    /// a Cephei Vector is is a specialisation of List that supports Cell notification events
    /// </summary>
    /// <typeparam name="T">type of object in the collection</typeparam>
    public interface IVector<T> : ICell, Base.IVector, IEnumerable<T> // , IList<T>
    {
        /// <summary>
        /// get a reference to the underlying native vector that can be used with C++ functions
        /// </summary>
        /// <remarks>
        /// The native vector will either be added by a factory at construction time, or the concrete implementation
        /// will override the generic function to instantiate a new object
        /// </remarks>
        INativeVector<T> getFeature (NativeFeature feature);

        /// <summary>
        /// index the vector with a reference from a matrix
        /// </summary>
        /// <param name="x"></param>
        /// <returns></returns>
        T this[int x] { get; set; }
        /// <summary>
        /// get the count of items
        /// </summary>
        int Count { get; }
        /// <summary>
        /// Add a new item to the vector
        /// </summary>
        /// <param name="t">item to add</param>
        void Add(T t);
    }

    /// <summary>
    /// a Cephei Matrix is a specialisation of a two dimensional array with Cell notification events
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public interface IMatrix<T> : ICell, Base.IMatrix, IEnumerable<IVector<T>> //IList<IVector<T>>, 
    {
        /// <summary>
        /// for conveniance provide a accessor that makes the matrix look like a 2d array
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        T this[int x, int y] { get; set; }

        /// <summary>
        /// get a reference to the underlying native vector that can be used with C++ functions
        /// </summary>
        /// <remarks>
        /// The native vector will either be added by a factory at construction time, or the concrete implementation
        /// will override the generic function to instantiate a new object
        /// </remarks>
        INativeMatrix<T> getFeature (NativeFeature feature);

        /// <summary>
        /// get the number of rows in the matrix
        /// </summary>
        int Rows { get; }
        /// <summary>
        /// get the number of columns in the matrix
        /// </summary>
        int Columns { get; }
        /// <summary>
        /// index the vector with a reference from a matrix
        /// </summary>
        /// <param name="x"></param>
        /// <returns></returns>
        IVector<T> this[int x] { get; set; }
        /// <summary>
        /// get the count of items
        /// </summary>
        int Count { get; }
        /// <summary>
        /// Add a new item to the vector
        /// </summary>
        /// <param name="t">item to add</param>
        void Add(IVector<T> t);
    }

    /// <summary>
    /// A Cephei cube is a specialisation of a three dimensional array with Cell notification events
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public interface ICube<T> : ICell, Base.ICube, IEnumerable<IMatrix<T>> //IList<IMatrix<T>>, 
    {
        /// <summary>
        /// for conveniance provide a accessor that makes the matrix look like a 3d array
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="z"></param>
        /// <returns></returns>
        T this[int x, int y, int z] { get; set; }

        /// <summary>
        /// get a reference to the underlying native vector that can be used with C++ functions
        /// </summary>
        /// <remarks>
        /// The native vector will either be added by a factory at construction time, or the concrete implementation
        /// will override the generic function to instantiate a new object
        /// </remarks>
        INativeCube<T> getFeature (NativeFeature feature);

        int Rows { get; }
        int Columns { get; }
        int Slices { get; }

        /// <summary>
        /// index the vector with a reference from a matrix
        /// </summary>
        /// <param name="x"></param>
        /// <returns></returns>
        IMatrix<T> this[int x] { get; set; }
        /// <summary>
        /// get the count of items
        /// </summary>
        int Count { get; }
        /// <summary>
        /// Add a new item to the vector
        /// </summary>
        /// <param name="t">item to add</param>
        void Add(IMatrix<T> t);
    }

    /// <summary>
    /// Define an abstract factory for collections of the specified type
    /// </summary>
    /// <typeparam name="T">type that will be returned from factory</typeparam>
    public interface INativeCollection_Factory<T>
    {
        /// <summary>
        /// Create a native vector for an existing CoVector<>
        /// </summary>
        /// <returns></returns>
        INativeVector<T> CreateNativeVector ();

        /// <summary>
        /// Create a native matricx for an existing CoMatrix<>
        /// </summary>
        /// <returns></returns>
        INativeMatrix<T> CreateNativeMatrix ();

        /// <summary>
        /// Create a native Cube for an existing CoCube<>
        /// </summary>
        /// <returns></returns>
        INativeCube<T> CreateNativeCube ();
    }

    /// <summary>
    /// Cephei collections are optimised for concurrent, distributed access
    /// to underlying native vectors, with minimal data copying.  They have been designed
    /// to be used in pricing servers where points in a vector can changed quickly.
    /// </summary>
    /// <typeparam name="T">underlying type</typeparam>
    public interface ICollection_Factory<T> : INativeCollection_Factory<T>
    {
        /// <summary>
        /// Create a hybrid List&lt&gt/std:vector&lt&gt of objects, with event notification of changes
        /// </summary>
        /// <returns>a new collection object</returns>
        IVector<T> CreateVector ();
        IVector<T> CreateVector (IEnumerable<T> source);

        /// <summary>
        /// Create a hybrid List&ltList&lt&gt&gt/std:vector&ltstd:vector&lt&gt &gt of objects, with event notification of changes
        /// </summary>
        /// <returns>a new collection object</returns>
        IMatrix<T> CreateMatrix ();
        IMatrix<T> CreateMatrix (IEnumerable<IEnumerable<T>> source);

        /// <summary>
        /// Create a hybrid List&ltList&ltList&lt&gt&gt&gt/std:vector&ltstd:vector&ltstd:vector&lt&gt &gt &gt of objects,  with event notification of changes
        /// </summary>
        /// <returns>a new collection object</returns>
        ICube<T> CreateCube ();
        ICube<T> CreateCube (IEnumerable<IEnumerable<IEnumerable<T>>> source);

        /// <summary>
        /// Create Cell of Vectors of Cells with the underlying type.  The implementation of the 
        /// vector will also subscribe to the ICell notification events of the Contained cells 
        /// </summary>
        /// <returns>a cell containing the new collection</returns>
        Generic.ICoCell<IVector<Generic.ICoCell<T>>> CreateCellVector ();
        Generic.ICoCell<IVector<Generic.ICoCell<T>>> CreateCellVector (IEnumerable<Generic.ICoCell<T>> source);

        /// <summary>
        /// Same as Cell&ltVector&ltCell&lt&gt&gt, but with IMatrix&lt&gt underlying
        /// </summary>
        /// <returns></returns>
        /// <returns>a cell containing the new collection</returns>
        Generic.ICoCell<IMatrix<Generic.ICoCell<T>>> CreateCellMatrix ();
        Generic.ICoCell<IMatrix<Generic.ICoCell<T>>> CreateCellMatrix (IEnumerable<IEnumerable<Generic.ICoCell<T>>> source);

        /// <summary>
        /// Same as Cell&ltMatrix&ltCell&lt&gt&gt&gt, but with ICube&lt&gt underlying
        /// </summary>
        /// <returns>a cell containing the new collection</returns>
        Generic.ICoCell<ICube<Generic.ICoCell<T>>> CreateCellCube ();
        Generic.ICoCell<ICube<Generic.ICoCell<T>>> CreateCellCube (IEnumerable<IEnumerable<IEnumerable<Generic.ICoCell<T>>>> source);
    }
    public interface IDouble_Factory : ICollection_Factory<double> 
    {
        Generic.ICoCell<double> Create ();
        Generic.ICoCell<double> Create (double d);
    }

    public interface IInt_Factory : ICollection_Factory<int>
    {
        Generic.ICoCell<int> Create ();
        Generic.ICoCell<int> Create (int d);
    }

    public interface IUInt_Factory : ICollection_Factory<UInt32>
    {
        Generic.ICoCell<uint> Create ();
        Generic.ICoCell<uint> Create (uint d);
    }

    public interface ILong_Factory : ICollection_Factory<long>
    {
        Generic.ICoCell<long> Create ();
        Generic.ICoCell<long> Create (long d);
    }

    public interface IULong_Factory : ICollection_Factory<UInt64>
    {
        Generic.ICoCell<ulong> Create ();
        Generic.ICoCell<ulong> Create (ulong d);
    }

    public interface IDateTime_Factory : ICollection_Factory<DateTime>
    {
        Generic.ICoCell<DateTime> Create ();
        Generic.ICoCell<DateTime> Create (DateTime d);
    }

    public interface IBool_Factory : ICollection_Factory<bool>
    {
        Generic.ICoCell<bool> Create ();
        Generic.ICoCell<bool> Create (bool d);
    }

    public interface IString_Factory : ICollection_Factory<string>
    {
        Generic.ICoCell<string> Create ();
        Generic.ICoCell<string> Create (string d);
    }

}
